home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 August: Tool Chest / Dev.CD Aug 99 TC.toast / What's New? / Development Kits / Hardware / Mac OS USB DDK v1.3a1 / Examples / MouseModule / MouseModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-16  |  17.3 KB  |  516 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MouseModule.c
  3.  
  4.     Contains:    HID Module for USB Mouse
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12.  
  13. /*
  14.     Notes to developers:
  15.     
  16.     1. The WatchDog functionality is *NOT* needed in your drivers.  It is part of an experiment to determine
  17.     if IntReads are ever dropped on the floor.  It was left in (but disabled) and checked into the 
  18.     projector database so that the coding effort wasn't lost.  We do not believe that IntReads are lost, so
  19.     your drivers should not need this WatchDog functionality.
  20.     
  21.     2. Apple reserves the right to do the following:
  22.         Release Mouse or Keyboard drivers that are vendor specific for Apple products
  23.         Release said mouse or keyboard drivers in binary form (but not necessarily in source form)
  24.         Prevent 3rd parties from writing generic drivers
  25.  
  26. */
  27.  
  28.  
  29. #include <Types.h>
  30. #include <Devices.h>
  31. #include <processes.h>
  32. #include <DriverServices.h>
  33. #include <USB.h>
  34. #include <LowMem.h>
  35.  
  36. #include "MouseModule.h"
  37.  
  38. #define    EnableWatchDog    0
  39.  
  40. usbMousePBStruct myMousePB;
  41. usbMousePBStruct watchDogPB;
  42.  
  43. void InitParamBlock(USBReference theInterfaceRef, USBPB * paramblock)
  44. {
  45.     paramblock->usbReference = theInterfaceRef;
  46.     paramblock->pbVersion = kUSBCurrentPBVersion;
  47.     
  48.     paramblock->usb.cntl.WIndex = 0;             
  49.     paramblock->usb.cntl.WValue = 0;
  50.     
  51.     paramblock->usbBuffer = nil;        
  52.     paramblock->usbActCount = 0;
  53.     paramblock->usbReqCount = 0;
  54.     paramblock->usbFlags = 0;
  55.     paramblock->usbOther = 0;
  56.     
  57.     paramblock->usbStatus = noErr;
  58. }
  59.  
  60.  
  61.  
  62. Boolean immediateError(OSStatus err)
  63. {
  64.     return((err != kUSBPending) && (err != noErr) );
  65. }
  66.  
  67. void MouseInitiateTransaction(USBPB *pb)
  68. {
  69. usbMousePBStruct *pMousePB;
  70. OSStatus myErr;
  71.  
  72.     pMousePB = (usbMousePBStruct *)(pb);
  73.     pMousePB->transDepth++;
  74.     if (pMousePB->transDepth < 0)
  75.     {
  76.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth < 0 (initiation)", pMousePB->pb.usbRefcon );
  77.     }
  78.     
  79.     if (pMousePB->transDepth > 1)
  80.     {
  81.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth > 1 (initiation)", pMousePB->pb.usbRefcon );
  82.     }
  83.     
  84.     if (pMousePB->driverRemovalPending)
  85.     {
  86.         pMousePB->pb.usbRefcon = kReturnFromDriver;
  87.         return;
  88.     }
  89.  
  90.     switch(pMousePB->pb.usbRefcon & ~kRetryTransaction)
  91.     {
  92.         case kConfigureInterface:
  93.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  94.             
  95.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  96.             pMousePB->pb.usbRefcon |= kCompletionPending;
  97.             
  98.             myErr = USBConfigureInterface( &pMousePB->pb );
  99.             if(immediateError(myErr))
  100.             {
  101.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kConfigureInterface - immediate error", myErr);
  102.                 pMousePB->pb.usbRefcon = kReturnFromDriver;
  103.             }
  104.             break;
  105.         
  106.         case kSetProtocol:
  107.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  108.             
  109.             pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  110.             pMousePB->pb.usb.cntl.BRequest = kHIDRqSetProtocol;
  111.             pMousePB->pb.usb.cntl.WValue = kHIDBootProtocolValue; 
  112.             pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
  113.             
  114.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  115.             pMousePB->pb.usbRefcon |= kCompletionPending;
  116.         
  117.             myErr = USBDeviceRequest(&pMousePB->pb);
  118.             if (immediateError(myErr))
  119.             {
  120.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kSetProtocol - immediate error", myErr);
  121.             }
  122.             break;
  123.             
  124.         case kSetIdleRequest:
  125.             USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Do a SetIdle on non-Apple mice, as some 3rd party mice don't send reports on button up", pMousePB->pipeRef);
  126.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  127.             
  128.             pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  129.             
  130.             pMousePB->pb.usb.cntl.BRequest = kHIDRqSetIdle;
  131.             pMousePB->pb.usb.cntl.WValue = ((24/4)<<8);                 // force a read completion if idle for more than 24ms
  132.             pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
  133.             
  134.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  135.             pMousePB->pb.usbRefcon |= kCompletionPending;
  136.  
  137.             myErr = USBDeviceRequest(&pMousePB->pb);
  138.             if(immediateError(myErr))
  139.             {
  140.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kSetIdleRequest - immediate error", myErr);
  141.             }
  142.             break;
  143.  
  144.         case kFindPipe:
  145.             InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
  146.             
  147.             pMousePB->pb.usbFlags = kUSBIn;
  148.             pMousePB->pb.usbClassType = kUSBInterrupt;
  149.             
  150.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  151.             pMousePB->pb.usbRefcon |= kCompletionPending;
  152.         
  153.             myErr = USBFindNextPipe( &pMousePB->pb );
  154.             if((immediateError(myErr)) || (pMousePB->pb.usbBuffer == nil))
  155.             {
  156.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kFindPipe - immediate error", myErr);
  157.                 pMousePB->pb.usbRefcon = kReturnFromDriver;
  158.             }
  159.             
  160.             break;
  161.         
  162.         case kReadInterruptPipe:
  163.             InitParamBlock(pMousePB->pipeRef, &pMousePB->pb);
  164.  
  165.             pMousePB->pb.usbBuffer = (Ptr)pMousePB->hidReport;
  166.             pMousePB->pb.usbReqCount = pMousePB->maxPacketSize;
  167.             pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;    
  168.             
  169.             pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  170.             pMousePB->pb.usbRefcon |= kCompletionPending;
  171.         
  172.             myErr = USBIntRead(&pMousePB->pb);
  173.             if(immediateError(myErr))
  174.             {
  175.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Read Interrupt Pipe (ImmediateError)", myErr);
  176.             }
  177.             break;
  178.             
  179.         default:
  180.             USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Transaction initiated with bad refcon value", pMousePB->pb.usbRefcon);
  181.             pMousePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  182.             break;
  183.     }
  184.     
  185. // At this point the control is returned to the system.  If a USB transaction
  186. // has been initiated, then it will call the Complete procs
  187. // (below) to handle the results of the transaction.
  188. }
  189.  
  190. void WatchDogCompletionProc(USBPB *pb)
  191. {
  192. usbMousePBStruct *pWatchDogPB;
  193. OSStatus myErr;
  194. UInt32    delayTime = 0;
  195.  
  196.     pWatchDogPB = (usbMousePBStruct *)(pb);
  197.     if (!pWatchDogPB->driverRemovalPending)
  198.     {
  199.         delayTime = 50;        // come back in 50ms if we're currently processing a completion callback
  200.         if (myMousePB.pb.usbRefcon & kCompletionInProgess)
  201.         {
  202.             USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog occurred while processing a completion callback (check again in 50ms)", myMousePB.pb.usbRefcon);
  203.         }
  204.         else
  205.         {
  206.             switch(pWatchDogPB->watchDogState)
  207.             {
  208.                 case kDelay10Seconds:
  209.                     
  210.                     if (pWatchDogPB->watchDogActivityFlag)
  211.                     {
  212.                         USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - Mouse activity detected", pWatchDogPB->watchDogState);
  213.                         delayTime = 10000;
  214.                         pWatchDogPB->watchDogAbortFlag = false;
  215.                     }
  216.                     else
  217.                     {
  218.                         USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - No mouse activity detected, aborting pipe", pWatchDogPB->watchDogState);
  219.                         delayTime = 1000;
  220.                         pWatchDogPB->watchDogState = kCheckForAbort;
  221.                     }
  222.                     break;
  223.         
  224.                 case kCheckForAbort:
  225.                     delayTime = 10000;
  226.                     pWatchDogPB->watchDogState = kDelay10Seconds;
  227.                     
  228.                     if (pWatchDogPB->watchDogAbortFlag)
  229.                     {
  230.                         USBExpertStatusLevel(5, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - Abort detected in completion routine", pWatchDogPB->watchDogState);
  231.                     }
  232.                     else
  233.                     {
  234.                         USBExpertStatusLevel(4, pWatchDogPB->interfaceRef, kMouseModuleName": Watchdog - No abort detected, restarting int read", pWatchDogPB->watchDogState);
  235.                         InitParamBlock(myMousePB.pipeRef, &myMousePB.pb);
  236.             
  237.                         myMousePB.pb.usbBuffer = (Ptr)myMousePB.hidReport;
  238.                         myMousePB.pb.usbReqCount = myMousePB.maxPacketSize;
  239.                         myMousePB.pb.usb.cntl.WIndex = myMousePB.interfaceDescriptor.interfaceNumber;    
  240.                         
  241.                         myMousePB.pb.usbCompletion = (USBCompletion)MouseCompletionProc;
  242.                         myMousePB.pb.usbRefcon = kReadInterruptPipe + kCompletionPending;
  243.                     
  244.                         myErr = USBIntRead(&myMousePB.pb);
  245.                         if(immediateError(myErr))
  246.                         {
  247.                             USBExpertFatalError(myMousePB.interfaceRef, kUSBInternalErr, kMouseModuleName": Watchdog - Read Interrupt Pipe (ImmediateError)", myErr);
  248.                         }
  249.                     }
  250.                     pWatchDogPB->watchDogAbortFlag = false;
  251.                     break;
  252.             }
  253.             pWatchDogPB->watchDogActivityFlag = false;
  254.             pWatchDogPB->watchDogAbortFlag = false;
  255.             if (pWatchDogPB->watchDogState == kCheckForAbort)
  256.             {
  257.                 USBAbortPipeByReference(pWatchDogPB->pipeRef);
  258.             }
  259.         }
  260.         InitParamBlock( pWatchDogPB->interfaceRef, &pWatchDogPB->pb );
  261.         
  262.         pWatchDogPB->pb.usbBuffer = 0;
  263.         pWatchDogPB->pb.usbActCount = 0;
  264.         pWatchDogPB->pb.usbReqCount = delayTime;            
  265.         
  266.         pWatchDogPB->pb.usbRefcon = 0;
  267.         pWatchDogPB->pb.usbCompletion = (USBCompletion)WatchDogCompletionProc;
  268.         
  269.         USBDelay(&pWatchDogPB->pb);
  270.         
  271.     }
  272.     return;
  273. }
  274.  
  275.  
  276. void MouseCompletionProc(USBPB *pb)
  277. {
  278. usbMousePBStruct     *pMousePB;
  279. unsigned char        * errstring;
  280. USBPipeState         pipeState;
  281.  
  282. #if EnableWatchDog
  283. OSStatus            myErr;
  284. #endif
  285.  
  286.     pMousePB = (usbMousePBStruct *)(pb);
  287.     pMousePB->transDepth--;
  288.     if (pMousePB->transDepth < 0)
  289.     {
  290.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth < 0 (completion)", pMousePB->pb.usbRefcon );
  291.     }
  292.     
  293.     if (pMousePB->transDepth > 1)
  294.     {
  295.         USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth > 1 (completion)", pMousePB->pb.usbRefcon );
  296.     }
  297.     
  298.     pMousePB->pb.usbRefcon |= kCompletionInProgess;                                            // make certain the watchdog routine doesn't race us
  299.     
  300.     if(pMousePB->pb.usbStatus != noErr)                                                        // was there an error?
  301.     {
  302.         switch(pMousePB->pb.usbRefcon & kStageMask)                                            // yes, so show where the error occurred
  303.         {
  304.             case kSetProtocol:                    errstring = kMouseModuleName": Error during kSetProtocol"; break;
  305.             case kSetIdleRequest:                  errstring = kMouseModuleName": Error during kSetIdleRequest"; break;
  306.             case kConfigureInterface:            errstring = kMouseModuleName": Error during kConfigureInterface"; break;
  307.             case kFindPipe:                      errstring = kMouseModuleName": Error during kFindPipe"; break;
  308.             case kReadInterruptPipe:
  309.                 {
  310.                 errstring = kMouseModuleName": Error during ReadInterruptPipe";
  311.                 LMSetMouseButtonState(0x80);    // release any possibly held-down mouse button
  312.                 break;
  313.                 }
  314.             default:                              errstring = kMouseModuleName": Error occurred, but state is unknown"; break;
  315.         };
  316.         
  317.         pMousePB->pb.usbRefcon &= (kStageMask + kCompletionInProgess);                        // save the refcon & completion in progress flag
  318.         pMousePB->pb.usbRefcon |= kRetryTransaction;                                        // set up to retry the transaction
  319.         pMousePB->retryCount--;
  320.         
  321.         // don't put out a fatal error message if an expected abort has occurred
  322.         if ((pMousePB->pb.usbStatus != kUSBAbortedError) || (watchDogPB.watchDogState != kCheckForAbort))
  323.         {
  324.             USBExpertFatalError(pMousePB->interfaceRef, pMousePB->pb.usbStatus, errstring, (pMousePB->pb.usbRefcon & kStageMask));
  325.         }
  326.         
  327.         if ((pMousePB->retryCount == 1) && ((pMousePB->pb.usbRefcon & kStageMask) == kSetIdleRequest))
  328.         {
  329.             USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Device doesn't accept SetIdle", pMousePB->interfaceRef);
  330.             pMousePB->pb.usbRefcon = kFindPipe;
  331.             pMousePB->pb.usbStatus = noErr;
  332.         }
  333.         else
  334.         {
  335.             if ((pMousePB->pb.usbStatus == kUSBAbortedError) && (watchDogPB.watchDogState == kCheckForAbort))
  336.             {
  337.                 USBExpertStatusLevel(5, pMousePB->interfaceRef, kMouseModuleName": Expected abort has occurred - retry int read", pMousePB->interfaceRef);
  338.                 if (pMousePB->pipeRef)
  339.                 {    
  340.                         watchDogPB.watchDogAbortFlag = true;                                // flag that we had the abort
  341.                 }
  342.                 USBGetPipeStatusByReference(pMousePB->pipeRef, &pipeState);                    // yes, so what it's state?
  343.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  344.                 {
  345.                     USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe is open and stalled, clearing stall...", pMousePB->interfaceRef);
  346.                     USBClearPipeStallByReference(pMousePB->pipeRef);
  347.                 }
  348.             }
  349.             else if ((!pMousePB->retryCount) || (pMousePB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  350.             {                                                                                // or received an abort?
  351.                 USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe abort or unable to recover from error", pMousePB->interfaceRef);
  352.                 pMousePB->pb.usbRefcon = kReturnFromDriver + kCompletionInProgess;            // if so, just exit.
  353.                 pMousePB->intPipeAborted = true;    
  354.             }
  355.             else                                                                            // if it didn't abort and there's retries left, then...
  356.             {
  357.                 if (pMousePB->pipeRef)                                                        // check if the pipe is open.
  358.                 {
  359.                     USBGetPipeStatusByReference(pMousePB->pipeRef, &pipeState);                // yes, so what it's state?
  360.                     if (pipeState != kUSBActive)                                            // if it's not active, try to clear it.  It might be stalled...
  361.                     {
  362.                         USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe is open and stalled, clearing stall...", pMousePB->interfaceRef);
  363.                         USBClearPipeStallByReference(pMousePB->pipeRef);
  364.                     }
  365.                 }
  366.             }
  367.         }
  368.     }
  369.     else
  370.     {
  371.         pMousePB->pb.usbRefcon &= ~kRetryTransaction;
  372.         pMousePB->retryCount = kMouseRetryCount;
  373.     }
  374.  
  375.     if (pMousePB->pb.usbRefcon & kCompletionPending)             
  376.     {                                                
  377.         pMousePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  378.         switch(pMousePB->pb.usbRefcon & kStageMask)
  379.         {
  380.             case kConfigureInterface:
  381.                 pMousePB->pb.usbRefcon = kSetProtocol + kCompletionInProgess;
  382.                 break;
  383.                 
  384.             case kSetProtocol:
  385.                 if (kVendorID_AppleComputer == USBToHostWord(pMousePB->deviceDescriptor.vendor) )
  386.                 {
  387.                     pMousePB->pb.usbRefcon = kFindPipe + kCompletionInProgess;
  388.                 }
  389.                 else
  390.                 {
  391.                     pMousePB->pb.usbRefcon = kSetIdleRequest + kCompletionInProgess;
  392.                 }
  393.                 break;
  394.                 
  395.             case kSetIdleRequest:
  396.                 pMousePB->pb.usbRefcon = kFindPipe + kCompletionInProgess;
  397.                 break;
  398.                 
  399.             case kFindPipe:
  400.                 pMousePB->maxPacketSize = pMousePB->pb.usb.cntl.WValue;
  401.                 pMousePB->pipeRef = pMousePB->pb.usbReference;
  402.                 pMousePB->pb.usbRefcon = kReadInterruptPipe + kCompletionInProgess;
  403.  
  404.                 USBExpertStatus( watchDogPB.interfaceRef, kMouseModuleName": Initialize watchdog", 0);
  405.                 InitParamBlock( watchDogPB.interfaceRef, &watchDogPB.pb );
  406.                 
  407.                 watchDogPB.pipeRef = pMousePB->pipeRef;
  408.                 watchDogPB.watchDogState = kDelay10Seconds;
  409.                 
  410.                 watchDogPB.pb.usbBuffer = 0;
  411.                 watchDogPB.pb.usbActCount = 0;
  412.                 watchDogPB.pb.usbReqCount = 20000;            // check for mouse activity every twenty seconds
  413.                 watchDogPB.watchDogActivityFlag = false;
  414.                 
  415.                 watchDogPB.pb.usbRefcon =  0;
  416.                 watchDogPB.pb.usbCompletion = (USBCompletion)WatchDogCompletionProc;
  417.                 
  418.                 
  419. #if EnableWatchDog
  420.                 myErr = USBDelay(&watchDogPB.pb);
  421.                 if(immediateError(myErr))
  422.                 {
  423.                     USBExpertFatalError(pb->usbReference, myErr, kMouseModuleName": Setting up watchdog - USBDelay immediate error", 0);
  424.                 }
  425. #endif
  426.  
  427.                 break;
  428.                 
  429.             case kReadInterruptPipe:
  430.                 watchDogPB.watchDogActivityFlag = true;
  431.                 if (myMousePB.pNotificationRoutine)
  432.                 {
  433.                     (*myMousePB.pNotificationRoutine)(myMousePB.notificationRefcon, pMousePB->pb.usbActCount, (void *)pMousePB->hidReport, myMousePB.interfaceRef);
  434.                 }
  435.                 pMousePB->pb.usbRefcon = kReadInterruptPipe + kCompletionInProgess;
  436.                 break;
  437.  
  438.             default:
  439.                 USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Transaction completed with bad refcon value", pMousePB->pb.usbRefcon );
  440.                 pMousePB->pb.usbRefcon = kUndefined + kReturnFromDriver + kCompletionInProgess;
  441.                 break;
  442.         }
  443.     }
  444.     
  445.     pMousePB->pb.usbRefcon &= ~(kCompletionInProgess);
  446.     if (!(pMousePB->pb.usbRefcon & kReturnFromDriver) && (!pMousePB->driverRemovalPending))
  447.         MouseInitiateTransaction(pb);
  448. }
  449.  
  450.  
  451. void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBReference theInterfaceRef)
  452. {
  453. #pragma unused (interfacenum)
  454.  
  455. static Boolean beenThereDoneThat = false;
  456.  
  457.     if(beenThereDoneThat)
  458.     {
  459.         USBExpertFatalError(theInterfaceRef, kUSBInternalErr, kMouseModuleName" is not reentrant", 0);
  460.         return;
  461.     }
  462.     beenThereDoneThat = true;
  463.     
  464.     // DebugStr("\pIn Mouse Interface Entry routine");
  465.  
  466.     watchDogPB.watchDogState = 0;
  467.     watchDogPB.watchDogAbortFlag = false;
  468.     watchDogPB.watchDogActivityFlag = false;
  469.     watchDogPB.driverRemovalPending = false;
  470.     watchDogPB.interfaceRef = theInterfaceRef;        
  471.     watchDogPB.pipeRef = nil;        
  472.     watchDogPB.pb.pbLength = sizeof(usbMousePBStruct);
  473.  
  474.     myMousePB.driverRemovalPending = false;
  475.     myMousePB.intPipeAborted = false;    
  476.  
  477.     myMousePB.deviceDescriptor = *pDeviceDescriptor;                
  478.     myMousePB.interfaceDescriptor = *pInterfaceDescriptor;            
  479.     
  480.     myMousePB.transDepth = 0;                            
  481.     myMousePB.retryCount = kMouseRetryCount;
  482.       
  483.     myMousePB.pSHIMInterruptRoutine = nil;
  484.     myMousePB.pSavedInterruptRoutine = nil;
  485.     
  486.     myMousePB.notificationRefcon = 0;
  487.     myMousePB.pNotificationRoutine = NotifyRegisteredHIDUser;
  488.  
  489.     myMousePB.interfaceRef = theInterfaceRef;        
  490.     myMousePB.pipeRef = nil;        
  491.     
  492.     InitParamBlock(theInterfaceRef, &myMousePB.pb);
  493.     
  494.     myMousePB.pb.usbReference = theInterfaceRef;
  495.     myMousePB.pb.pbLength = sizeof(usbMousePBStruct);
  496.     myMousePB.pb.usbRefcon = kConfigureInterface;        
  497.     
  498.     if ((myMousePB.deviceDescriptor.vendor == USB_CONSTANT16(0x046e)) &&
  499.         (myMousePB.deviceDescriptor.product == USB_CONSTANT16(0x6782)))
  500.     {
  501.         myMousePB.unitsPerInch = (Fixed)(100<<16);
  502.     }
  503.     else
  504.     {
  505.         myMousePB.unitsPerInch = (Fixed)(400<<16);
  506.     }
  507.     
  508.     myMousePB.pCursorDeviceInfo = 0;                
  509.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  510.  
  511.     MouseInitiateTransaction(&myMousePB.pb);
  512. }
  513.  
  514.  
  515.  
  516.